#include "precompiled.h"
#include "equipcom.h"
using namespace weo::engine::character;
using namespace weo::engine::item;
using namespace std;
bool Equipcom::s_UseSpecial = true;
bool Equipcom::s_UseWeaponProcs = true;
bool Equipcom::s_IsInitialized = false;
std::map<unsigned int const,weo::engine::item::Attribute> Equipcom::s_SpecialMap;
Equipcom::Equipcom()
{
    if(!s_IsInitialized)
    {
        LoadSpecialValuesFromXml();
        s_IsInitialized = true;
    }
    m_Mode = 0;
    ResetBase();
    ResetBuffs();
    ResetEquip();
    ResetTest();
}
void Equipcom::LoadSpecialValuesFromXml()
{
    string file_name = "specialvalues.xml";
    ticpp::Document *doc = new (UseGC) ticpp::Document();
    try
    {
        doc->LoadFile(file_name);
        ticpp::Element *root = doc->FirstChildElement("specialValues", true);
        if(root != NULL)
        {
            ticpp::Element *pValue = root->FirstChildElement("specialValue",false);
            while(pValue != NULL)
            {
                unsigned int id = boost::lexical_cast<unsigned int,std::string>(pValue->GetAttribute("id"));
                std::string name = pValue->GetAttribute("name");
                ticpp::Element *pAttr = pValue->FirstChildElement("attribute",true);
                Attribute attr;
                attr.fromXmlElement(pAttr);
                Equipcom::s_SpecialMap[id] = attr;
                pValue = pValue->NextSiblingElement(false);
            }
        }
        delete doc;
    }
    catch( ticpp::Exception& ex )
    {
    }
}
float Equipcom::Get(const unsigned int index) const
{
    switch(m_Mode)
    {
    case 0:
        return m_Base[index];
        break;
    case 1:
        return m_Buff[index];
        break;
    case 2:
        return m_Equip[index];
        break;
    case 3:
        return m_Base[index] + m_Buff[index] + m_Equip[index];
        break;
    case 4:
        return m_Test[index];
    default:
        return m_Base[index] + m_Buff[index] + m_Equip[index];
        break;
    }
}
void Equipcom::Set(const unsigned int index, const float value)
{
    switch(m_Mode)
    {
    case 0:
        m_Base[index] = value;
        break;
    case 1:
        m_Buff[index] = value;
        break;
    case 2:
        m_Equip[index] = value;
        break;
    case 4:
        m_Test[index] = value;
    default:
        break;
    }
}
float& Equipcom::operator[](const unsigned int index)
{
    switch(m_Mode)
    {
    case 0:
        return m_Base[index];
        break;
    case 1:
        return m_Buff[index];
        break;
    case 2:
        return m_Equip[index];
        break;
    case 3:
        {
            m_Combined[index] =  m_Base[index]+ m_Buff[index] + m_Equip[index];
            return m_Combined[index];
            break;
        }
    case 4:
        return m_Test[index];
        break;
    default:
        break;
    }
}
Attribute Equipcom::handleSpecial(unsigned int value)
{
    if(!Equipcom::s_UseSpecial) return Attribute("None",0);
    switch(value)
    {
    case 1000010:
        {
            if(!Equipcom::s_UseWeaponProcs) return  Attribute("None",0);
            return Attribute("Agility",0.35f*120); // mongoose
            break;
        }
    case 1000011:
        {
            if(!Equipcom::s_UseWeaponProcs) return  Attribute("None",0);
            return Attribute("HasteRating",0.35f*2*weo::engine::item::HasteRating); // mongoose
            break;
        }
    case 1000020:
        {
            if(!Equipcom::s_UseWeaponProcs) return  Attribute("None",0);
            return Attribute("Strength",15); // crusader
            break;
        }
    case 1000030:
        {
            if(!Equipcom::s_UseWeaponProcs) return  Attribute("None",0);
            if(m_HasExecutioner) return Attribute("None",0);
            m_HasExecutioner = true;
            float exec_uptime = 0.35f;
            float armor_before = MobArmor - m_Equip[50];
            float armor_diff = 840.0f*exec_uptime*(2.0f*armor_before+21115.0f)/(19435.0f+1680.0f*exec_uptime+2.0f*armor_before);
            return Attribute("ArmorPenetration",armor_diff);
            break;
        }
    default:
        const std::map<unsigned int const,weo::engine::item::Attribute>::const_iterator it = Equipcom::s_SpecialMap.find(value);
        if(it != Equipcom::s_SpecialMap.end())
        {
            return it->second;
        }
        switch(m_Mode)
        {
        case 0:
            m_SpecialsBase.insert(value);
            break;
        case 1:
            m_SpecialsBuff.insert(value);
            break;
        case 2:
            m_SpecialsEquip.insert(value);
            break;
        case 3:
            break; // should never happen no insert in mode 3 (running)
        case 4:
            m_SpecialsTest.insert(value);
            break;
        default:
            break;
        }
        return Attribute("None",0);
        break;
    }
}
bool Equipcom::hasSpecial(float value)
{
    if(m_SpecialsBase.count(value) > 0 || m_SpecialsBuff.count(value) > 0 || m_SpecialsEquip.count(value) > 0 || m_SpecialsTest.count(value) > 0) return true;
    return false;
}